pub mod test;
pub use test::*;

use super::BackupResult;
use super::BackupStatistics;
use super::DeduperProduct;
use crate::recipe::ChunkPointer;
use crate::recipe::FileInfo;
use crate::chunk::Chunk;

use parking_lot::Mutex;
use pipelines::{Sender,Receiver};

use std::fmt::Debug;
use std::sync::Arc;
use std::time::Instant;

pub struct ChunkExtractor {
    statistics:Arc<Mutex<BackupStatistics>>,
}

impl ChunkExtractor {
    pub fn new(statistics:Arc<Mutex<BackupStatistics>>) -> Self {
        Self {
            statistics:statistics,
        }
    }
    
    pub fn extract<P:ChunkPointer+Debug+Send>(&self,out:&Sender<ExtractorProduct<P>>,recv:Receiver<DeduperProduct<P>>) -> BackupResult<()> {
        let mut cost_time:u128 = 0;
        for product in recv {
            match product {
                DeduperProduct::FileInfo(info) => {
                    out.send(ExtractorProduct::FileInfo(info));
                }
                DeduperProduct::ChunkPointer(chunk_pointer) => {
                    out.send(ExtractorProduct::ChunkPointer(chunk_pointer));
                },
                DeduperProduct::Chunk(chunk) => {
                    let now = Instant::now();
                    chunk.sf_init();
                    cost_time += now.elapsed().as_micros();
                    out.send(ExtractorProduct::Chunk(chunk));
                },
            }
        }
        self.statistics.lock().set_extract_phase_time(cost_time);
        Ok(())
    }
}

pub enum ExtractorProduct<P:ChunkPointer+Send> {
	FileInfo(FileInfo),
	ChunkPointer(Box<P>),
	Chunk(Arc<Chunk>),
}
